Code:
alias clonescan {
  if ($ial == $false) {
    ; note: if the IAL isn't on before this, ouch!  Nothing will be in the IAL!
    .ial on 
    return
  }
  var %i = 1, %chan = $1, %win = $+(@clones,.,$network,.,%chan), %addr
  if (!$window(%win)) {
    window -Czd %win 100 50 690 460
    titlebar %win Clones list for $+($network,:) $nick(%chan,0) users currently on %chan
    font %win 12 arial bold
  }
  if (%chan !ischan) {
    aline -p %win 4ERROR no such channel $iif(%chan,as %chan)
    return
  }
  while ($nick(%chan, %i)) {
    var %smask = $address($v1,%i)
    if ($ialchan(%smask,%chan,0) > 1) && (%smask !isin %addr) {
      %addr = %addr $address($nick(%chan,%i),2)
      aline -p 12 %win $timestamp $chr(42) Found ( $+ $ialchan(%smask,%chan,0) $+ ) Clones in $+($chr(40),%chan,$chr(41)) from ( $+ $gettok(%smask,2,64) $+ )
      var %cnt = 1
      while ($ialchan(%smask,%chan,%cnt)) {
        aline -p %win $timestamp $chr(42) $+(%cnt,.) $gettok($v1, 1, 33)
        inc %cnt
      }
      aline -p %win -
    }
    inc %i
  }
  if (!%addr) {
    aline %win $timestamp 4,1No clones found on %chan
  }
  else {
    aline %win $timestamp  4,1Scan on %chan complete!
  }

}

So, why would this be faster?

A few reasons:

Every time through the loop, you were re-evaluating the window name a minimum of 4 times. 300 people in a channel means a minimum of 1200 evaluations of that one string, which isn't changing. Slow down.

With that in mind, we do the same thing with the $address($nick(%chan,%i), 2). This is an IAL lookup to begin with, so instead of doing a few as possible lookups, you were doing double, which in a single pass would be something like 11 lookups. This cuts it in half to 3-4.

The while loops were changed as well, so that the full count isn't required for every-iteration-of-the-loop.

Anyway, my tests of the above code in a 370 user channel takes about a second on my underclocked P4.