Realmente no trabalho faço coisas mais complexas que envolvem o próprio negócio e suas particularidades e quase sempre usamos o auto complete para trechos assim, só revisamos é claro. Mas eu tentaria converter a string em um array, depois percorrer esse array com um for manual.
i = 0; i < string.length; i++
dentro do for faria um if pegando o indexOf do i e válido se é diferente do i atual
if (string.indexOf(string[i]) !== i) {
return false;
}
[...]
return true;
Como o indexOf vai retornar o primeiro elemento, ao procurar a string "aabc" a primeira vez seria index 0 !== 0 (não, tudo ok), na segunda iteração, index 0 !== 1 (sim, pegou index 0 novamente porque o "a" apareceu já no index 0)
Ao pesquisar sobre vi que da para fazer melhor ainda usando o Set, se não precisar remover acentos, maiúsculas, espaços em brancos e outras coisas, poderia só fazer um new Set da string, que já vai salvar cada caracter único como uma chave desse Set e validar se tem o mesmo tamanho da string original.
function temCaracteresUnicos(str) {
return new Set(str).size === str.length;
}