Since you are using your C library from C# via C++/CLI layer, it sounds like your link relationships look like this:
(C# application)--dynamic-->(C++/CLI DLL)--static-->(C library)
Background:
Because you stated that you have no way of modifying or otherwise fixing your C library, you really have no way of solving the thread-safety problem without duplicating the C library in memory somehow, which will effectively duplicate the global data which is/are certainly causing the threading conflicts.
No matter how you look at it, your only way of solving this via DLL duplication (your current approach) will require you to know how many duplicates you need ahead of time, and each one of those DLLs will need slightly different exported symbol names (for example, each will need a different class or namespace name for your C++/CLI managed object class). As you stated, this is indeed crude (and I will add hard to manage and impossible to scale).
Solution:
I think your better and cleaner option is via EXE duplication. For this, you will insert a new EXE in front of your C++/CLI DLL and link to it dynamically via IPC mechanism of your choice (IPC Mechanisms in C# - Usage and Best Practices). Lets call this EXE your service EXE. If you instantiate a service EXE for each thread in your main C# application, then each service EXE will load its own copy of the C++/CLI DLL and consequently its own version of the C library. This means that each thread is operating on a copy of the C library via a service EXE.
Here is what your link relationships would look like:
(C# application)--IPC-->(C# service EXE)--dynamic-->(C++/CLI DLL)--static-->(C library)
In physical file terms, it would look like this:
MainApp.exe--IPC-->ServiceApp.exe--dynamic-->CppCliWrapper.dll
To optimize this solution, you should try to avoid heavy thread creation / deletion since that involves creation / deletion of a service EXE. For example, you might pre-allocate X threads on startup and use those threads throughout your application lifecycle. You might also consider batching your operations to optimize the IPC overhead. All of this depends on the needs and details of your application.
To take this even further, you could potentially scale this solution across machines if you choose an IPC mechanism that works over TCP/IP. You could then farm out your operations across as many machines as you like. This is how a lot of companies turn DLLs into horizontally scalable services. It's not as easy as it sounds, but food for though in case you need to scale this thing up.