I think the way to go would be to write the client in a way such that you dynamically alter the client code and verify the use of thusly created code on the server.
E.g. have a namespace like this
window.mynamespace = {
foo : function(){
// some stuff here
},
bar : function(){
// some more stuff here
}
}
which contains all your client code and make all your server methods require a token that is the result of a previous dynamic evaluation of the code base. make this harder by redefining methods and changing method names. Here are a few sample challenges (this only makes sense if challenges are created dynamically and not predictable). All contain a task first and then a challenge that will be used to create the authorization token for the next request. (These are response objects from the ajax calls). Basically the task will be eval'd and the result of the eval'd challenge will be the next token.
{
task: "mynamespace.baz=mynamespace.foo;mynamespace.foo=undefined;",
challenge: "mynamespace[11].toString().substr(10,22)"
// get part of a well-known functions source code
}
{
task: "mynamespace.bar=function(){ /* new code here */ }",
challenge: "var xy=0;mynamespace.each(function(item){xy+=item.toString().lastIndexOf(';')}); xy"
// accumulate the last index of a semicolon in all elements
// of the namespace
}
To beat that and still get valid authorization tokens, the client would have to write an entire javascript emulation layer. Although that can be done, I would try to make the server code change in fundamental ways very often to make this technique almost impossible (so the emulation layer won't know what to emulate).