Here's my version of camelCase function:
var camelCase = (function () {
    var DEFAULT_REGEX = /[-_]+(.)?/g;
    function toUpper(match, group1) {
        return group1 ? group1.toUpperCase() : '';
    }
    return function (str, delimiters) {
        return str.replace(delimiters ? new RegExp('[' + delimiters + ']+(.)?', 'g') : DEFAULT_REGEX, toUpper);
    };
})();
It handles all of the following edge cases:
- takes care of both underscores and hyphens by default (configurable with second parameter)
 
- string with unicode characters
 
- string that ends with hyphens or underscore
 
- string that has consecutive hyphens or underscores
 
Here's a link to live tests: http://jsfiddle.net/avKzf/2/
Here are results from tests:
- input: "ab-cd-ef", result: "abCdEf"
 
- input: "ab-cd-ef-", result: "abCdEf"
 
- input: "ab-cd-ef--", result: "abCdEf"
 
- input: "ab-cd--ef--", result: "abCdEf"
 
- input: "--ab-cd--ef--", result: "AbCdEf"
 
- input: "--ab-cd-__-ef--", result: "AbCdEf"
 
Notice that strings that start with delimiters will result in a uppercase letter at the beginning.
If that is not what you would expect, you can always use lcfirst.
Here's my lcfirst if you need it:
function lcfirst(str) {
    return str && str.charAt(0).toLowerCase() + str.substring(1);
}