It will be a lot of hard work! And clojurescript will need a separate implementation from clojure due to the absence of weak references in JS. Much easier to use wrappers than re-invent the wheel.
Under the hood there is a lot of imperative code to keep reasonable performance. A purely functional implementation with no dirty tricks will lose observable sharing for one.
One thing has got me interested though. Closure is a LISP-like language, and I believe LISP languages are really good at meta programming. I wonder if closure could be used for generating source code for implementations in other languages.
Correct me if I'm wrong. LISP programs are code as data, and the used functions within a scope can be intercepted and replaced via let expressions, these replaced expressions could generate an AST of some made up intermediate language with the bear minimal to implement sodium, then this AST could be processed different ways to produce different implementations.
After a bit more research LISP is an amazing language. It has full reflection of its own source code. Though a wrapper should be able to be tweaked to provide syntactic improvements still without reinventing the wheel. E.g. sodium objects reference by a lambda would not need to be explicitly listed for the garbage collector used in the JS version as the reference sodium objects could be searched within the lambda automatically.