First, a disclaimer: I'm not deeply familiar with the uniform access principal so you may want to take this with a grain of salt. That said, I would argue that Clojure does observe a uniform access principle: function calls.

The key quote on Wikipedia seems to be that "all services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation", and that's exactly the case with function calls in Clojure. In fact, *everything* in Clojure (and other Lisps) is a function call except for [special forms](http://clojure.org/special_forms) and [macros](http://clojure.org/macros) - and macros actually are functions, with the distinction that they operate on source code. You can even specify function call behavior for your own types by implementing `clojure.lang.IFn`:

    (deftype Invokable []
      clojure.lang.IFn
      (invoke [this]
        :was-invoked))

    (def invokable (Invokable.))
    (invokable)                  ;=> :was-invoked

You may have in mind the use of keywords as functions, which are most specifically associated with hash-maps, but you can actually implement that behavior for different types as well. Here's a silly example because I couldn't come up with anything better that involved IO and wasn't too long:

    (deftype WeirdKlass []
      clojure.lang.ILookup
      (valAt [this k not-found]
        (let [home (System/getProperty "user.home")
              file (io/file home (name k))]
         (if (.isFile file)
           (slurp file)
           not-found)))
      (valAt [this k]
        (.valAt this k nil)))

    (def klass (WeirdKlass.))

    ;; assuming you have a file at $HOME/testfile
    (:testfile klass)        ;=> "test content!"
    (:blah klass)            ;=> nil
    (:blah klass :not-found) ;=> :not-found